package susebs.pb.travel_server.utils;


import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriUtils;
import susebs.pb.travel_server.domain.Locations;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 地图检索基础服务，包含了调用百度地图所需的各种参数
 */
@Component
public class MapInfoBasicUtil {
    public static String URL = "https://api.map.baidu.com/place/v2/search?";//地址信息请求地址
    public static String DETAILURL = "https://api.map.baidu.com/place/v2/detail?";//地址详情请求地址
    public static String CODENIURL = "https://api.map.baidu.com/reverse_geocoding/v3?";//地址逆编码请求地址
    public static String CODEURL = "https://api.map.baidu.com/geocoding/v3?";//地址编码请求地址
    private static String AK = "0Eed0TeyLRDZvX513Q8GDcDQkq4AAuIs";//AK密钥
    /**
     * 基础参数集
     * 根据检索关键词返回一个参数map集合，来自搜索模块
     * @return 参数集
     */
    static LinkedHashMap<String,String> getParams(){
        LinkedHashMap<String, String> params = new LinkedHashMap<>();
        params.put("output", "json");
        params.put("ak", AK);
        params.put("scope","2");
        return params;
    }

    /**
     * 处理和解析地址并完成请求，此处暂时用作获取各个行政区的酒店信息列表
     * @param strUrl , 百度api提供的访问地址
     * @param param，参数集
     * @return 结果集的json字符串
     * @throws Exception
     */
    static String requestGetAK(String strUrl , Map<String , String> param) throws Exception{
        if (strUrl == null || strUrl.length() <= 0 || param == null || param.size() <= 0) {
            return "";
        }

        StringBuffer queryString = new StringBuffer();
        queryString.append(strUrl);
        for (Map.Entry<?, ?> pair : param.entrySet()) {
            queryString.append(pair.getKey() + "=");
            //    第一种方式使用的 jdk 自带的转码方式  第二种方式使用的 spring 的转码方法 两种均可
            //    queryString.append(URLEncoder.encode((String) pair.getValue(), "UTF-8").replace("+", "%20") + "&");
            //解决uid="abc",pair=uid中，""会被解析的问题
            String strValue = (String) pair.getValue();
            if (strValue.startsWith("\"") && strValue.endsWith("\"")) {
                strValue = strValue.substring(1, strValue.length() - 1);
            }
            queryString.append(UriUtils.encode(strValue, "UTF-8") + "&");
        }

        if (queryString.length() > 0) {
            queryString.deleteCharAt(queryString.length() - 1);
        }

        java.net.URL url = new URL(queryString.toString());
        System.out.println(queryString.toString());
        URLConnection httpConnection = (HttpURLConnection) url.openConnection();
        httpConnection.connect();

        InputStreamReader isr = new InputStreamReader(httpConnection.getInputStream());
        BufferedReader reader = new BufferedReader(isr);
        StringBuffer buffer = new StringBuffer();
        String line;
        while ((line = reader.readLine()) != null) {
            buffer.append(line);
        }
        reader.close();
        isr.close();
        return buffer.toString();
    }

    /**
     * 检索指定行政区内的某一类地址信息
     * @param query 检索关键词，如酒店，景点等
     * @param region 检索行政区，可以是汉字“北京”等，也可以行政区编码，具体参考开发文档
     * @return 地址信息结果集
     * @throws Exception 抛错
     */
    public static JsonNode getAddr(String query, String region) throws Exception {
        LinkedHashMap<String, String> params = getParams();
        params.put("query", query);
        params.put("region", region);
        params.put("scope","2");
        String s = requestGetAK(URL, params);//百度API，数据查询
//        数据处理
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readTree(s);
    }

    /**
     * 地址解析：传入经纬度返回结构化地址
     * @param lng，经度
     * @param lat，维度
     * @return 结构化地址
     */
    public static String addressResolution(Double lng,Double lat ) throws Exception {
        //地址解析
        LinkedHashMap<String, String> params = getParams();
        params.put("coordtype", "wgs84ll");
        params.put("extensions_poi", "0");
        params.put("location",lat+","+lng);
//        params.put("location","31.225696563611,121.49884033194");
        String s = requestGetAK(CODENIURL, params);

        //处理数据
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.readTree(s);
        return jsonNode.get("result").get("formatted_address").asText();
    }

    /**
     * 地址编码：输入结构化地址获取经纬度
     */
    public static Locations addressCoding(String addr) throws Exception {
        Locations location = new Locations();
        LinkedHashMap<String, String> params = getParams();

        params.put("address", addr);

        String s = requestGetAK(CODEURL, params);

        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode node = objectMapper.readTree(s).get("result").get("location");

        location.setLng(node.get("lng").asDouble());
        location.setLat(node.get("lat").asDouble());
        return location;
    }
}
